package com.liuya.safe.util;

import com.liuya.common.StringUtil;
import com.liuya.db.sql.ContextValue;
import com.liuya.db.sql.Value;
import com.liuya.db.sql.xml.DefineVariable;
import com.liuya.db.sql.xml.Query;
import com.liuya.safe.client.pojo.Application;
import com.liuya.safe.client.pojo.FieldMetadata;
import com.liuya.safe.client.pojo.UserType;
import com.liuya.safe.client.service.ApplicationManager;
import com.liuya.safe.client.service.UserTypeManager;
import com.liuya.safe.exception.AuthException;
import com.liuya.safe.model.SafeUser;
import com.liuya.safe.policy.service.QueryManagerService;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ValidationException;

import javax.servlet.http.HttpServletRequest;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class AuthUtil {

    public static void extractContextValueFields(com.liuya.db.sql.Query query, Collection fields) {
        ArrayList values = query.getValues();

        for (Iterator iter2 = values.iterator(); iter2.hasNext(); ) {
            Value v = (Value) iter2.next();

            if (v instanceof ContextValue) {
                ContextValue cv = (ContextValue) v;
                String key = cv.getKey();

                fields.add(key);
            }
        }
    }

    public static void extractContextValueFields(DefineVariable[] variables, QueryManagerService queryManager, Collection fields) {
        for (int i = 0; i < variables.length; i++) {
            DefineVariable var = variables[i];

            if (var.getContextValue() != null) {
                fields.add(var.getContextValue().getKey());
            } else if (var.getQueryRef() != null) {
                String refId = var.getQueryRef().getId();

                com.liuya.safe.model.SafeQuery query = queryManager.getQuery(refId);
                ArrayList values = query.getSqlQuery().getValues();

                for (Iterator iter = values.iterator(); iter.hasNext(); ) {
                    Value v = (Value) iter.next();

                    if (v instanceof com.liuya.db.sql.ContextValue) {
                        com.liuya.db.sql.ContextValue cv = (com.liuya.db.sql.ContextValue) v;
                        String key = cv.getKey();

                        fields.add(key);
                    }
                }
            }
        }
    }

    public static void extractBusinessDataFields(DefineVariable[] variables, Collection fields) {
        for (int i = 0; i < variables.length; i++) {
            DefineVariable var = variables[i];

            if (var.getHintValue() != null) {
                fields.add(var.getHintValue().getKey());
            }
        }
    }

    public static Query getTemplateQuery() {
        String s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<query name=\"\" ds=\"\"" + "    isRawSQL=\"false\" type=\"sql\">" + "    <select isDistinct=\"false\" mappingClass=\"\"/>" + "    <from>" + "       <table schema=\"\" name=\"\" alias=\"\"/>" + "    </from>" + "    <where>" + "        <expressionGroup linker=\"AND\"/>" + "    </where>" + "    <groupBy/>" + "    <orderBy/>" + "    <rawSQL>" + "        <content xml:space=\"preserve\"><![CDATA[]]></content>" + "        <select isDistinct=\"false\"/>" + "    </rawSQL>" + "    <storedProcedure>" + "        <content></content>" + "        <select isDistinct=\"false\"/>" + "    </storedProcedure>" + "</query>";
        try {
            Query query = (Query) Query.unmarshal(new StringReader(s));
            query.getQueryTypeSequence().getFrom().removeAllTable();
            return query;
        } catch (MarshalException e) {
            throw new AuthException(e);
        } catch (ValidationException e) {
            throw new AuthException(e);
        }
    }

    public static Object convertUserId(HttpServletRequest req, String strUserId) {
        FieldMetadata[] fields = getUserType(req).getUserMetadata().getMainTableMetadata().getFields();
        String idClass = "";
        for (int i = 0; i < fields.length; i++) {
            FieldMetadata field = fields[i];
            if (field.getName().equals(SafeUser.idFieldName)) {
                idClass = field.getJavaType(); // return;
            }
        }

        if ("int".equals(idClass) || "java.lang.Integer".equals(idClass)) {
            return new Integer(strUserId);
        } else if ("long".equals(idClass) || "java.lang.Long".equals(idClass)) {
            return new Long(strUserId);
        }

        return strUserId;
    }

    /**
     * Return an UserType with name stored in session or just return a default
     * one. The store key is WebConstants.CURR_USER_TYPE.
     *
     * @param req
     * @return an UserType or null
     */
    public static UserType getUserType(HttpServletRequest req) {
        UserTypeManager userTypeMng = Factory.getUserTypeManager();

        String name = (String) req.getSession().getAttribute(Constants.CURR_USER_TYPE);
        if (StringUtil.isEmpty(name)) {
            // get a default one
            Collection types = userTypeMng.getAllUserTypes();
            if (types.size() > 0) {
                UserType type = (UserType) types.iterator().next();

                name = type.getName();
                req.getSession().setAttribute(Constants.CURR_USER_TYPE, name);

                return type;
            } else {
                return null;
            }
        } else {
            return userTypeMng.getUserType(name);
        }
    }

    public static Application getApplication(HttpServletRequest req) {
        ApplicationManager appMng = Factory.getApplicationManager();

        String name = (String) req.getSession().getAttribute(Constants.CURR_APP);
        if (StringUtil.isEmpty(name)) {
            // get a default one
            Collection apps = appMng.getAllApplications();
            if (apps.size() > 0) {
                Application app = (Application) apps.iterator().next();
                name = app.getName();
                req.getSession().setAttribute(Constants.CURR_APP, name);

                return app;
            }
            return null;
        } else {
            return appMng.getApplication(name);
        }
    }

}
